package com.factory.socket;

import com.factory.MyApplication;
import com.factory.controller.SocketDataController;
import com.factory.domain.deviceTable;
import com.factory.domain.warnTable;
import com.factory.mapper.DeviceTableMapper;
import com.factory.mapper.WarnTableMapper;
import com.factory.utils.DateUtils;
import com.factory.utils.HexStringUtils;
import com.factory.utils.HexUtil;
import com.factory.websocket.WebSocketEndpoint;
import com.github.s7connector.api.DaveArea;
import com.github.s7connector.api.S7Connector;
import com.github.s7connector.api.factory.S7ConnectorFactory;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Author dongyaoyao
 * @Date 2025/4/7 10:08
 * @Version 1.0
 */
@Component
public class S7MultiDBHandler {
    private static S7Connector connector;
    private static final Logger log = LoggerFactory.getLogger(MyApplication.class);
    @Autowired
    private WebSocketEndpoint webSocketEndpoint;
    @Autowired
    private SocketDataController socketDataController;
    private volatile boolean isRunning = true;

    // 工厂方法
    @PostConstruct
    public void init() {
        try {
            connector = S7ConnectorFactory
                    .buildTCPConnector()
                    .withHost("192.168.181.52") //
                    .withRack(0) //架机号  可选
                    .withSlot(1) //插槽号  可选
                    .build();
            isRunning = true;
            System.out.println("PLC连接成功");

        } catch (Exception e) {
            System.out.println("检查PLC连接是否存在");
            isRunning = false;
        }
    }

    /*每隔一秒读取一次数据*/
    @Scheduled(fixedDelay = 1000)// 每1秒执行一次
    public void redCurrentData() {
        if (isRunning) {
            MessageDecoder messageDecoder = new MessageDecoder();
            //液压
            byte[] DBD19_20 = connector.read(DaveArea.DB, 103, 2, 19);
            List<String> DBD19_20Fluid = messageDecoder.dealBodyOpen(HexStringUtils.toHexString(DBD19_20));
            log.info("增加报警数据"+DBD19_20Fluid);
            //滑油
            byte[] DBD26_28 = connector.read(DaveArea.DB, 103, 3, 26);
            List<String> DBD26_28Slippery = messageDecoder.dealBodyOpen(HexStringUtils.toHexString(DBD26_28));
            /**
             * 高压系统
             */
            byte[] DBD2_94 = connector.read(DaveArea.DB, 10, 96, 2);
            byte[] DBD98_142 = connector.read(DaveArea.DB, 10, 63, 98);
            List<String> DBD2_94Water = messageDecoder.dealBody(HexStringUtils.toHexString(DBD2_94));
            List<String> DBD98_142Water = messageDecoder.dealBodyOpen(HexStringUtils.toHexString(DBD98_142));
            List<String> combinedWater = messageDecoder.concatArrays(DBD98_142Water, DBD2_94Water);
            JSONObject objectWater = new JSONObject();
            List<JSONObject> listWater = new ArrayList<>();
            for (int i = 0; i < combinedWater.size(); i++) {
                JSONObject jsonWater = new JSONObject();
                jsonWater.put("id", i);
                jsonWater.put("data", combinedWater.get(i));
                listWater.add(jsonWater);
                if (i == 34) {
                    alarmStorage(1L, "高压水系统", (long) i, "温度26", combinedWater.get(i));
                }
                if (i == 36) {
                    alarmStorage(1L, "高压水系统", (long) i, "温度27", combinedWater.get(i));
                }
                if (i == 42) {
                    alarmStorage(1L, "高压水系统", (long) i, "液压18", combinedWater.get(i));
                }
                if (i == 44) {
                    alarmStorage(1L, "高压水系统", (long) i, "液压21", combinedWater.get(i));
                }
            }
            objectWater.put("data", listWater);
            objectWater.put("type", 1);
            webSocketEndpoint.sendManyMessage(objectWater.toString());
            socketDataController.add(objectWater.toString(), 1L);
            /**
             * 低压水系统
             * */
            byte[] DBD2_102 = connector.read(DaveArea.DB, 11, 104, 2);
            byte[] DBD106_138 = connector.read(DaveArea.DB, 11, 57, 106);
            List<String> DBD2_102Water = messageDecoder.dealBody(HexStringUtils.toHexString(DBD2_102));
            List<String> DBD106_138Water = messageDecoder.dealBodyOpen(HexStringUtils.toHexString(DBD106_138));
            List<String> combinedLowWater = messageDecoder.concatArrays(DBD106_138Water, DBD2_102Water);
            JSONObject objectLowWater = new JSONObject();
            List<JSONObject> listLowWater = new ArrayList<>();
            for (int i = 0; i < combinedLowWater.size(); i++) {
                JSONObject jsonLowWater = new JSONObject();
                jsonLowWater.put("id", i);
                jsonLowWater.put("data", combinedLowWater.get(i));
                listLowWater.add(jsonLowWater);
                if (i == 30) {
                    alarmStorage(2L, "低压水系统", (long) i, "液压24", combinedLowWater.get(i));
                }
                if (i == 32) {
                    alarmStorage(2L, "低压水系统", (long) i, "温度23", combinedLowWater.get(i));
                }
            }
            objectLowWater.put("data", listLowWater);
            objectLowWater.put("type", 2);
            //log.info(objectLowWater.toString());
            webSocketEndpoint.sendManyMessage(objectLowWater.toString());
            socketDataController.add(objectLowWater.toString(), 2L);
            /**
             * 液压系统DB数据
             */
            byte[] DBD2_74 = connector.read(DaveArea.DB, 12, 76, 2);
            byte[] DBD78_158 = connector.read(DaveArea.DB, 12, 81, 78);
            List<String> DBD2_74Fluid = messageDecoder.dealBody(HexStringUtils.toHexString(DBD2_74));
            List<String> DBD78_158Fluid = messageDecoder.dealBodyOpen(HexStringUtils.toHexString(DBD78_158));
            List<String> combinedFluid = messageDecoder.concatArrays(DBD78_158Fluid, DBD2_74Fluid);
            List<String> allData = messageDecoder.concatArrays(combinedFluid, DBD19_20Fluid);
            //log.info("拼接数据"+allData);
            JSONObject jsonFluid = new JSONObject();
            List<JSONObject> listFluid = new ArrayList<>();
            for (int i = 0; i < allData.size(); i++) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("id", i);
                jsonObject.put("data", allData.get(i));
                listFluid.add(jsonObject);
                if (i == 62) {
                    alarmStorage(3L, "液压系统", (long) i, "温度6", allData.get(i));
                }
                if (i == 80) {
                    alarmStorage(3L, "液压系统", (long) i, "液位5", allData.get(i));
                }
            }
            jsonFluid.put("data", listFluid);
            jsonFluid.put("type", 3);
            webSocketEndpoint.sendManyMessage(jsonFluid.toString());
//            log.info(jsonFluid.toString());
            socketDataController.add(jsonFluid.toString(), 3L);
            /**
             * 滑油系统DB数据
             */
            byte[] DBD2_86 = connector.read(DaveArea.DB, 13, 88, 2);
            byte[] DBD90_168 = connector.read(DaveArea.DB, 13, 79, 90);
            List<String> DBD2_74Slippery = messageDecoder.dealBody(HexStringUtils.toHexString(DBD2_86));
            List<String> DBD78_158Slippery = messageDecoder.dealBodyOpen(HexStringUtils.toHexString(DBD90_168));
            List<String> combinedSlippery = messageDecoder.concatArrays(DBD78_158Slippery, DBD2_74Slippery);
            List<String> allDataSlippery = messageDecoder.concatArrays(combinedSlippery, DBD26_28Slippery);
            JSONObject objectSlippery = new JSONObject();
            List<JSONObject> listSlippery = new ArrayList<>();
            for (int i = 0; i < allDataSlippery.size(); i++) {
                JSONObject jsonSlippery = new JSONObject();
                jsonSlippery.put("id", i);
                jsonSlippery.put("data", allDataSlippery.get(i));
                listSlippery.add(jsonSlippery);
                if (i == 72) {
                    alarmStorage(4L, "滑油系统", (long) i, "压力14.5", allDataSlippery.get(i));
                }
                if (i == 78) {
                    alarmStorage(4L, "滑油系统", (long) i, "液位21", allDataSlippery.get(i));
                }
            }
            objectSlippery.put("data", listSlippery);
            objectSlippery.put("type", 4);
            webSocketEndpoint.sendManyMessage(objectSlippery.toString());
            //原始数据保存到数据
            //log.info(objectSlippery.toString());
            socketDataController.add(objectSlippery.toString(), 4L);
            /**
             * 高压空气
             */
            byte[] DBD0_7 = connector.read(DaveArea.DB, 14, 32, 0);
            byte[] DBD8_15 = connector.read(DaveArea.DB, 14, 15, 32);
            List<String> DBD0_74Air = messageDecoder.dealBody(HexStringUtils.toHexString(DBD0_7));
            List<String> DBD78_158Air = messageDecoder.dealBodyOpen(HexStringUtils.toHexString(DBD8_15));
            List<String> combinedAir = messageDecoder.concatArrays(DBD78_158Air, DBD0_74Air);
            JSONObject objectAir = new JSONObject();
            List<JSONObject> listAir = new ArrayList<>();
            for (int i = 0; i < combinedAir.size(); i++) {
                JSONObject jsonAir = new JSONObject();
                jsonAir.put("id", i);
                jsonAir.put("data", combinedAir.get(i));
                listAir.add(jsonAir);
                switch (i) {
                    case 0:
                        alarmStorage(5L, "高压空气系统", (long) i, "流量", allDataSlippery.get(i));
                        break;
                    case 2:
                        alarmStorage(5L, "高压空气系统", (long) i, "F4-压力", allDataSlippery.get(i));
                        break;
                    case 4:
                        alarmStorage(5L, "高压空气系统", (long) i, "F5-温度", allDataSlippery.get(i));
                        break;
                    case 6:
                        alarmStorage(5L, "高压空气系统", (long) i, "F6-露点", allDataSlippery.get(i));
                        break;
                    case 8:
                        alarmStorage(5L, "高压空气系统", (long) i, "F3-流量", allDataSlippery.get(i));
                        break;
                    case 10:
                        alarmStorage(5L, "高压空气系统", (long) i, "F17-压力", allDataSlippery.get(i));
                        break;
                    case 12:
                        alarmStorage(5L, "高压空气系统", (long) i, "F17-温度", allDataSlippery.get(i));
                        break;
                    case 14:
                        alarmStorage(5L, "高压空气系统", (long) i, "F17-湿度", allDataSlippery.get(i));
                        break;
                }
            }
            objectAir.put("data", listAir);
            objectAir.put("type", 5);
            webSocketEndpoint.sendManyMessage(objectAir.toString());
            //原始数据保存到数据
//            log.info(objectAir.toString());
            socketDataController.add(objectAir.toString(), 5L);
        }
    }

    private static DeviceTableMapper deviceTableMapper = null;

    @Autowired  //构造函数
    public S7MultiDBHandler(DeviceTableMapper deviceTableMapper) {
        S7MultiDBHandler.deviceTableMapper = deviceTableMapper;
    }

    /*修改DB数据*/
    public static void writeCurrentData(Long systemId, Long device_id, String bytes) {
        deviceTable deviceData = deviceTableMapper.selectDeviceTableById(systemId, device_id);
        log.info("测试数据是否打印：" + deviceData.toString());
        int TYPE = 0;
        switch (Math.toIntExact(deviceData.getSystemId())) {
            case 1:
                TYPE = 10;
                break;
            case 2:
                TYPE = 11;
                break;
            case 3:
                TYPE = 12;
                break;
            case 4:
                TYPE = 13;
                break;
            case 5:
                    TYPE=103;
                    break;
            case 6:
                TYPE=1;
                break;
        }
        //0 开关量  1模拟量
        switch (Math.toIntExact(deviceData.getType())) {
            case 0:
                connector.write(DaveArea.DB, TYPE, Math.toIntExact(deviceData.getPlcId()), HexUtil.hexStringToByteArray(bytes));
                break;
            case 1:
                connector.write(DaveArea.DB, TYPE, Math.toIntExact(deviceData.getPlcId()), HexUtil.floatStringToByteArray(bytes));
                break;
        }

    }

    //关闭连接
    public void close() {
        try {
            connector.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 报警数据保存数据库
     */
    private static WarnTableMapper warnTableMapper = null;

    public S7MultiDBHandler(WarnTableMapper warnTableMapper) {
        S7MultiDBHandler.warnTableMapper = warnTableMapper;
    }

    private void alarmStorage(Long systemId, String system_name, Long device_id, String device_name, String warn_context) {
        String alarmData = null;
        //log.info("都取数据：++"+warn_context);
        int decimal = Integer.parseInt(warn_context, 16);
        String binaryStr = Integer.toBinaryString(decimal);

        // 补全前导0，保持位数对齐
        binaryStr = String.format("%" + (warn_context.length() * 8) + "s", binaryStr).replace(' ', '0');
        char firstOne = binaryStr.charAt(7);
        char firstTwo = binaryStr.charAt(6);
        if (firstOne == 1) {
            alarmData = "低报警";
        } else if (firstTwo == 1) {
            alarmData = "高报警";
        } else {
            return;
        }
        Date alarmTime = DateUtils.getNewDateTime();
        warnTable warnTable = new warnTable();
        warnTable.setSystemId(systemId);
        warnTable.setSystemName(system_name);
        warnTable.setDeviceId(device_id);
        warnTable.setDeviceName(device_name);
        warnTable.setTime(alarmTime);
        warnTable.setWarnContext(alarmData);
        warnTableMapper.insertWarnTable(warnTable);
    }
}